<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: Dean <zxxjjforever@163.com>
// +----------------------------------------------------------------------
namespace plugins\server_data;

use cmf\lib\Plugin;
use think\Db;

class ServerDataPlugin extends Plugin
{

    public $info = [
        'name'        => 'ServerData',
        'title'       => '服务器数据',
        'description' => '服务器数据',
        'status'      => 1,
        'author'      => 'Hunuo',
        'version'     => '1.0'
    ];

    public $hasAdmin = 0;//插件是否有后台管理界面

    // 插件安装
    public function install()
    {
        return true;//安装成功返回true，失败false
    }

    // 插件卸载
    public function uninstall()
    {
        return true;//卸载成功返回true，失败false
    }

    public function adminDashboard()
    {
        $sysInfo =$this->GetsysInfo();
        // unset($sysInfo['cpu']);
        // pre($sysInfo,1);

        $sysInfo['cpu_use'] = '<tr><td align="center" colspan="8">数据获取中...</td></tr>';
        // pre($sysInfo['cpu_use'],1);

        // foreach ($data as $k => $v) {
        //     $CPU_Use .= $k.' '.$v['user']."%us,  ".$v['sys']."%sy,  ".$v['nice']."%ni, ".$v['idle']."%id,  ".$v['iowait']."%wa,  ".$v['irq']."%irq,  ".$v['softirq']."%softirq".'<br>';
        // }
        // $this->CPU_Use =$data['cpu0']['user']."%us,  ".$data['cpu0']['sys']."%sy,  ".$data['cpu0']['nice']."%ni, ".$data['cpu0']['idle']."%id,  ".$data['cpu0']['iowait']."%wa,  ".$data['cpu0']['irq']."%irq,  ".$data['cpu0']['softirq']."%softirq";
        
        // pre($CPU_Use,1);
        

        // pre($this->CPU_Use,1);
        // $this->CPU_Use =$data['cpu0']['user']."%us,  ".$data['cpu0']['sys']."%sy,  ".$data['cpu0']['nice']."%ni, ".$data['cpu0']['idle']."%id,  ".$data['cpu0']['iowait']."%wa,  ".$data['cpu0']['irq']."%irq,  ".$data['cpu0']['softirq']."%softirq";
        
        $isCpuUse = 1;
        if(!$this->OS()){
            $isCpuUse = 0;
        }

        $this->assign('hd', $this->GetDisk());
        $this->assign('server_info', $sysInfo);
        $this->assign('is_cpu_use', $isCpuUse);
        
        return [
            'width'  => 12,
            'view'   => $this->fetch('widget'),
            'plugin' => 'ServerData'
        ];
    }
    public function OS(){
        return  DIRECTORY_SEPARATOR=='/'?true:false;
    }
    public function GetsysInfo(){
        switch(PHP_OS) {
            case'Linux':
                $sysInfo = $this->sys_linux();
                break;
            case'FreeBSD':
                $sysInfo = $this->sys_freebsd();
                break;
            default:
                $sysInfo = '';
                break;
        }
        return  $sysInfo;
    }
    public function sys_linux(){ //linux系统探测
        // $str= @file("more /proc/cpuinfo");//获取CPU信息
        $str = shell_exec("more /proc/cpuinfo");

        // $str = substr($str,strripos($str, ':')+1);
        // pre($str,1);
        if(!$str)return  false;
        // $str= implode("",$str);
        @preg_match_all("/model\s+name\s{0,}\:+\s{0,}([\w\s\)\(\@.-]+)([\r\n]+)/s",$str, $model);//CPU 名称
        @preg_match_all("/cpu\s+MHz\s{0,}\:+\s{0,}([\d\.]+)[\r\n]+/",$str, $mhz);//CPU频率
        @preg_match_all("/cache\s+size\s{0,}\:+\s{0,}([\d\.]+\s{0,}[A-Z]+[\r\n]+)/",$str, $cache);//CPU缓存
        @preg_match_all("/bogomips\s{0,}\:+\s{0,}([\d\.]+)[\r\n]+/",$str, $bogomips);//
        if(is_array($model[1])){
            $cpunum= count($model[1]);
            $x1= $cpunum>1?' ×'.$cpunum:'';
            $mhz[1][0] =' | 频率:'.$mhz[1][0];
            $cache[1][0] =' | 二级缓存:'.$cache[1][0];
            $bogomips[1][0] =' | Bogomips:'.$bogomips[1][0];
            $res['cpu']['num'] = $cpunum;
            $res['cpu']['model'][] = $model[1][0].$mhz[1][0].$cache[1][0].$bogomips[1][0].$x1;
            if(is_array($res['cpu']['model']))$res['cpu']['model'] = implode("<br />", $res['cpu']['model']);
            if(is_array($res['cpu']['mhz']))$res['cpu']['mhz'] = implode("<br />", $res['cpu']['mhz']);
            if(is_array($res['cpu']['cache']))$res['cpu']['cache'] = implode("<br />", $res['cpu']['cache']);
            if(is_array($res['cpu']['bogomips']))$res['cpu']['bogomips'] = implode("<br />", $res['cpu']['bogomips']);
        }
        //服务器运行时间
        // $str = @file("/proc/uptime");
        $str = shell_exec("more /proc/uptime");
        $str = substr($str,strripos($str, ':')+1);

        if(!$str) return  false;
        $str           = explode(" ", $str);
        $str           = trim($str[0]);
        $min           = $str/60;
        $hours         = $min/60;
        $days          = floor($hours/24);
        $hours         = floor($hours-($days*24));
        $min           = floor($min-($days*60*24)-($hours*60));
        $res['uptime'] = $days."天".$hours."小时".$min."分钟";
        //内存
        // $str= @file("/proc/meminfo");
        $str= shell_exec("more /proc/meminfo");
        if(!$str)return  false;
        // pre($str);
        preg_match_all("/MemTotal\s{0,}\:+\s{0,}([\d\.]+).+?MemFree\s{0,}\:+\s{0,}([\d\.]+).+?Cached\s{0,}\:+\s{0,}([\d\.]+).+?SwapTotal\s{0,}\:+\s{0,}([\d\.]+).+?SwapFree\s{0,}\:+\s{0,}([\d\.]+)/s",$str, $buf);
        preg_match_all("/Buffers\s{0,}\:+\s{0,}([\d\.]+)/s",$str, $buffers);
        // pre($buf,1);
        $resmem['memTotal']   = round($buf[1][0]/1024, 2);
        $resmem['memFree']    = round($buf[2][0]/1024, 2);
        $resmem['memBuffers'] = round($buffers[1][0]/1024, 2);
        $resmem['memCached']  = round($buf[3][0]/1024, 2);
        $resmem['memCached']   = empty($resmem['memCached'])? 0 : $resmem['memCached'];

        $resmem['memUsed']          = $resmem['memTotal']-$resmem['memFree'];
        $resmem['memPercent']       = (floatval($resmem['memTotal'])!=0)?round($resmem['memUsed']/$resmem['memTotal']*100,2):0;
        $resmem['memRealUsed']      = $resmem['memTotal'] -$resmem['memFree'] -$resmem['memCached'] -$resmem['memBuffers'];//真实内存使用
        $resmem['memRealFree']      = $resmem['memTotal'] -$resmem['memRealUsed'];//真实空闲
        $resmem['memRealPercent']   = (floatval($resmem['memTotal'])!=0)?round($resmem['memRealUsed']/$resmem['memTotal']*100,2):0;//真实内存使用率
        $resmem['memCachedPercent'] = (floatval($resmem['memCached'])!=0)?round($resmem['memCached']/$resmem['memTotal']*100,2):0;//Cached内存使用率
        $resmem['swapTotal']   = round($buf[4][0]/1024, 2);
        $resmem['swapTotal']   = empty($resmem['swapTotal'])? 0 : $resmem['swapTotal'];
        $resmem['swapFree']    = round($buf[5][0]/1024, 2);
        $resmem['swapUsed']    = round($resmem['swapTotal']-$resmem['swapFree'], 2);
        $resmem['swapPercent'] = (floatval($resmem['swapTotal'])!=0)?round($resmem['swapUsed']/$resmem['swapTotal']*100,2):0;
        $resmem= $this->formatmem($resmem);//格式化内存显示单位
        $res = array_merge($res,$resmem);
        // pre($res,1);

        // // LOAD AVG 系统负载
        // $str= @file("/proc/loadavg");
        $str = shell_exec("more /proc/loadavg");
        $str = substr($str,strripos($str, ':')+1);
        if(!$str) return  false;
        $str= explode(" ", $str);
        $str= array_chunk($str, 4);
        $res['loadAvg'] = implode(" ", $str[0]);
        return  $res;
    }
    public function sys_freebsd(){ //freeBSD系统探测
        $res['cpu']['num']   = do_command('sysctl','hw.ncpu');//CPU
        $res['cpu']['model'] = do_command('sysctl','hw.model');
        $res['loadAvg']      = do_command('sysctl','vm.loadavg');//Load AVG  系统负载
        //uptime
        $buf= do_command('sysctl','kern.boottime');
        $buf= explode(' ',$buf);
        $sys_ticks= time()-intval($buf[3]);
        $min= $sys_ticks/60;
        $hours= $min/60;
        $days= floor($hours/24);
        $hours= floor($hours-($days*24));
        $min= floor($min-($days*60*24)-($hours*60));
        $res['uptime'] =$days.'天'.$hours.'小时'.$min.'分钟';
        //内存
        $buf= do_command('sysctl','hw.physmem');
        $resmem['memTotal'] =round($buf/1024/1024, 2);
        $str= do_command('sysctl','vm.vmtotal');
        preg_match_all("/\nVirtual Memory[\:\s]*\(Total[\:\s]*([\d]+)K[\,\s]*Active[\:\s]*([\d]+)K\)\n/i",$str, $buff, PREG_SET_ORDER);
        preg_match_all("/\nReal Memory[\:\s]*\(Total[\:\s]*([\d]+)K[\,\s]*Active[\:\s]*([\d]+)K\)\n/i",$str, $buf, PREG_SET_ORDER);
        $resmem['memRealUsed'] = round($buf[0][2]/1024, 2);
        $resmem['memCached']   = round($buff[0][2]/1024, 2);
        $resmem['memCached']   = empty($resmem['memCached'])? 0 : $resmem['memCached'];

        $resmem['memUsed'] =round($buf[0][1]/1024, 2)+$resmem['memCached'];
        $resmem['memFree'] =$resmem['memTotal']-$resmem['memUsed'];
        $resmem['memPercent'] = (floatval($resmem['memTotal'])!=0)?round($resmem['memUsed']/$resmem['memTotal']*100,2):0;
        $resmem['memRealPercent'] = (floatval($resmem['memTotal'])!=0)?round($resmem['memRealUsed']/$resmem['memTotal']*100,2):0;
        $resmem= $this->formatmem($resmem);
        $res= array_merge($res,$resmem);
        return $res;
    }
    public function do_command($cName,$args){ //执行系统命令FreeBSD
        $cName= empty($cName)?'sysctl':timr($cName);
        if(empty($args))return  false;
        $args= '-n '.$args;
        $buffers= '';
        $command= find_command($cName);
        if(!$command)return  false;
        if($fp= @popen("$command $args",'r')){
            while(!@feof($fp)) {
                $buffers.= @fgets($fp, 4096);
            }
            pclose($fp);
            return trim($buffers);
        }
        return  false;
    }
    public function find_command($cName){//确定shell位置
        $path= array('/bin','/sbin', '/usr/bin','/usr/sbin', '/usr/local/bin', '/usr/local/sbin');
        foreach($pathas as $p) {
            if(@is_executable("$p/$commandName"))return  "$p/$commandName";
        }
        return  false;
    }
    public function GetCPUUse(){
        // $data= @file('/proc/stat');
        $data = shell_exec("more /proc/stat");
        $data = substr($data,strripos($data, ':')+1);
        $data = explode('
',$data);
        // pre($data,1);

        
        // $cores= array();
        foreach($data as $line) {
            if(preg_match('/^cpu[0-9]/',$line)){
                // echo 1;die;
                $info= explode(' ',$line);
                $cores[]=array('user'=>$info[1],'nice'=>$info[2],'sys'=> $info[3],'idle'=>$info[4],'iowait'=>$info[5],'irq'=> $info[6],'softirq'=> $info[7]);
            }
        }

        // pre($cores,1);
        return $cores;
    }
    public function GetCPUPercent($CPU1,$CPU2){
        $num= count($CPU1);
        if($num!==count($CPU2))return ;
        $cups= array();
        for($i=0;$i < $num;$i++) {
            $dif= array();
            $dif['user']    =$CPU2[$i]['user'] -$CPU1[$i]['user'];
            $dif['nice']    =$CPU2[$i]['nice'] -$CPU1[$i]['nice'];
            $dif['sys']     =$CPU2[$i]['sys'] -$CPU1[$i]['sys'];
            $dif['idle']    =$CPU2[$i]['idle'] -$CPU1[$i]['idle'];
            $dif['iowait']  =$CPU2[$i]['iowait'] -$CPU1[$i]['iowait'];
            $dif['irq']     =$CPU2[$i]['irq'] -$CPU1[$i]['irq'];
            $dif['softirq'] =$CPU2[$i]['softirq'] -$CPU1[$i]['softirq'];
            $total= array_sum($dif);
            $cpu= array();
            foreach($dif as $x=>$y)
                $cpu[$x] =round($y/$total*100, 2);
            $cpus['cpu'.$i] = $cpu;
        }
        // pre($cpus,1);
        return $cpus;
    }
    public function GetDisk(){ //获取硬盘情况
        $d['t'] =round(@disk_total_space(".")/(1024*1024*1024),3);
        $d['f'] =round(@disk_free_space(".")/(1024*1024*1024),3);
        $d['u'] =$d['t']-$d['f'];
        $d['PCT'] = (floatval($d['t'])!=0)?round($d['u']/$d['t']*100,2):0;
        return $d;
    }
    private function formatmem($mem){//格试化内存显示单位
        if(!is_array($mem))return  $mem;
        $tmp= array(
            'memTotal','memUsed', 'memFree', 'memPercent',
            'memCached','memRealPercent',
            'swapTotal','swapUsed', 'swapFree', 'swapPercent'
        );
        foreach($mem as $k=>$v) {
            if(!strpos($k,'Percent')){
                // $v= $v<1024 ? $v.' G' : $v.' M';
                $v= $v.' M';
            }
            $mem[$k] =$v;
        }
        foreach($tmp as $v) {
            $mem[$v] =$mem[$v]?$mem[$v]:0;
        }
        return $mem;
    }
    public function GetNetWork(){ //网卡流量
        $strs= @file("/proc/net/dev");
        $lines= count($strs);
        for($i=2;$i < $lines;$i++) {
            preg_match_all("/([^\s]+):[\s]{0,}(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/",$strs[$i],$info );
            $res['OutSpeed'][$i] = $info[10][0];
            $res['InputSpeed'][$i] = $info[2][0];
            $res['NetOut'][$i] = $this->formatsize($info[10][0]);
            $res['NetInput'][$i] = $this->formatsize($info[2][0]);
            $res['NetWorkName'][$i] = $info[1][0];
        }
        return $res;
    }
    public function formatsize($size) {//单位转换
        $danwei=array(' B ',' K ',' M ',' G ',' T ');
        $allsize=array();
        $i=0;
        for($i= 0; $i <5; $i++) {
            if(floor($size/pow(1024,$i))==0){break;}
        }
        for($l= $i-1;$l >=0; $l--) {
            $allsize1[$l]=floor($size/pow(1024,$l));
            $allsize[$l]=$allsize1[$l]-$allsize1[$l+1]*1024;
        }
        $len=count($allsize);
        for($j= $len-1;$j >=0; $j--) {
            $fsize=$fsize.$allsize[$j].$danwei[$j];
        }
        return $fsize;
    }
    public function phpexts(){ //以编译模块
        $able= get_loaded_extensions();
        $str= '';
        foreach($able as $key => $value) {
            if($key!=0 &&$key%13==0) {
                $str.= '<br />';
            }
            $str.= "$value&nbsp;&nbsp;";
        }
        return $str;
    }
    public function show($varName){//检测PHP设置参数
        switch($result= get_cfg_var($varName)){
            case 0:
                return '<font color="red">×</font>';
            break;
            case 1:
                return '<font color="green">√</font>';
            break;
            default:
                return $result;
            break;
        }
    }
    public function GetDisFuns(){
        $disFuns=get_cfg_var("disable_functions");
        $str= '';
        if(empty($disFuns)){
            $str= '<font color=red>×</font>';
        }else{
            $disFunsarr=  explode(',',$disFuns);
            foreach($disFunsarr as $key=>$value) {
                if($key!=0 &&$key%8==0) {
                    $str.= '<br />';
                }
                $str.= "$value&nbsp;&nbsp;";
            }
        }
        return $str;
    }
    public function isfun($funName='',$j=0){// 检测函数支持
        if(!$funName || trim($funName) =='' || preg_match('~[^a-z0-9\_]+~i',$funName, $tmp)) return '错误';
        if(!$j){
            return (function_exists($funName) !== false) ?'<font color="green">√</font>' : '<font color="red">×</font>';
        }else{
            return (function_exists($funName) !== false) ?'√' : '×';
        }
    }
    public function GetGDVer(){
        $strgd= '<font color="red">×</font>';
        if(function_exists(gd_info)) {
            $gd_info= @gd_info();
            $strgd= $gd_info["GD Version"];
        }
        return $strgd;
    }
    public function GetZendInfo(){
        $zendInfo= array();
        $zendInfo['ver'] = zend_version()?zend_version():'<font color=red>×</font>';
        $phpv= substr(PHP_VERSION,2,1);
        $zendInfo['loader'] =$phpv>2?'ZendGuardLoader[启用]':'Zend Optimizer';
        if($phpv>2){
            $zendInfo['html'] = get_cfg_var("zend_loader.enable")?'<font color=green>√</font>':'<font color=red>×</font>';
        }else if(function_exists('zend_optimizer_version')){
            $zendInfo['html'] = zend_optimizer_version();
        }else{
            $zendInfo['html']= (get_cfg_var("zend_optimizer.optimization_level") ||
                                get_cfg_var("zend_extension_manager.optimizer_ts") ||
                                get_cfg_var("zend.ze1_compatibility_mode") ||
                                get_cfg_var("zend_extension_ts"))?'<font color=green>√</font>':'<font color=red>×</font>';
        }
        return $zendInfo;
    }
    public function GetIconcube(){
        $str= '<font color=red>×</font>';
        if(extension_loaded('ionCube Loader')){
            $ys= ionCube_Loader_version();
            $gm= '.'.(int)substr($ys, 3, 2);
            $str= $ys.$gm;
        }
        return $str;
    }
    public function CHKModule($cName){
        if(empty($cName))return  '错误';
        $str= phpversion($cName);
        return empty($str)?'<font color=red>×</font>':$str;
    }
    public function GetDBVer($dbname){
        if(empty($dbname))return  '错误';
        switch($dbname) {
            case'mysql':
                if(function_exists("mysql_get_server_info")){
                    $s= @mysql_get_server_info();
                    $s= $s ? '&nbsp; mysql_server 版本：'.$s:'';
                    $c= @mysql_get_client_info();
                    $c= $c ? '&nbsp; mysql_client 版本：'.$c:'';
                    return $s.$c;
                }
                return '';
                break;
            case'sqlite':
                if(extension_loaded('sqlite3')){
                    $sqliteVer= SQLite3::version();
                    $str= '<font color=green>√</font>';
                    $str.= 'SQLite3　Ver'.$sqliteVer['versionString'];
                }else{
                    $str= $this->isfun('sqlite_close');
                    if(strpos($str,'√')!==false){
                        $str.= '&nbsp; 版本：'.sqlite_libversion();
                    }
                }
                return $str;
                break;

            default:
                return '';
                break;
        }
    }
}
